import { useAppStore } from '@/store';
type EventListener = (data: any) => void;

class SocketService {
  private static instance: SocketService;
  private listeners: Record<string, EventListener[]> = {};
  private socketTask: UniApp.SocketTask | null = null;
  private isConnected = false;

  private constructor() {}

  public static getInstance(): SocketService {
    if (!SocketService.instance) {
      SocketService.instance = new SocketService();
    }
    return SocketService.instance;
  }

  // 建立连接
  public connect(url: string): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.isConnected) {
        console.warn('WebSocket 已连接');
        return resolve();
      }

      this.socketTask = uni.connectSocket({
        url: `${url}&userId=${useAppStore().$state.userInfo.userId}`,
        fail: (err) => {
          console.log(err);
        },
        complete: () => {},
      });

      if (!this.socketTask) {
        reject('socket连接失败');
      }

      this.socketTask.onOpen(() => {
        console.log('WebSocket 连接成功');
        this.isConnected = true;
        resolve();
      });

      this.socketTask.onMessage((res) => {
        this.handleMessage(res.data as string);
      });

      this.socketTask.onError((err) => {
        console.error('WebSocket 连接失败:', err);
        this.isConnected = false;
        reject(err);
      });

      this.socketTask.onClose(() => {
        console.log('WebSocket 已关闭');
        this.isConnected = false;
      });
    });
  }

  // 注册事件监听器
  public on(eventName: string, listener: EventListener): void {
    if (!this.listeners[eventName]) {
      this.listeners[eventName] = [];
    }
    this.listeners[eventName].push(listener);
  }

  // 取消事件监听器
  public off(eventName: string, listener: EventListener): void {
    if (!this.listeners[eventName]) return;

    this.listeners[eventName] = this.listeners[eventName].filter((l) => l !== listener);
  }

  // 触发事件监听器
  private emit(eventName: string, data: any): void {
    const listeners = this.listeners[eventName];
    if (listeners && listeners.length > 0) {
      listeners.forEach((listener) => listener(data));
    } else {
      console.warn(`无监听器处理事件: ${eventName}`);
    }
  }

  // 处理接收到的消息
  private handleMessage(data: string): void {
    try {
      if (data[0] === '0') return;
      const bracketIndex = data.indexOf('[');
      if (bracketIndex === -1) {
        console.warn('数据格式不正确，忽略:', data);
        return;
      }

      const jsonData = data.substring(bracketIndex);
      const parsedArray = JSON.parse(jsonData);
      if (!Array.isArray(parsedArray) || parsedArray.length < 2) {
        console.error('数据格式不符合事件要求:', jsonData);
        return;
      }

      const eventName = parsedArray[0];
      console.log('🚀 ~ SocketService ~ handleMessage ~ eventName:', eventName);
      console.log('🚀 ~ SocketService ~ handleMessage ~ parsedArray:', parsedArray[1]);
      const eventData = eventName === 'message' ? parsedArray[1] : JSON.parse(parsedArray[1]);

      this.emit(eventName, eventData);
    } catch (error) {
      console.error('解析消息失败:', error, '数据:', data);
    }
  }

  // 发送消息
  public sendMessage(message: any): Promise<void> {
    return new Promise((resolve, reject) => {
      if (!this.isConnected || !this.socketTask) {
        return reject(new Error('WebSocket 未连接'));
      }

      this.socketTask.send({
        data: JSON.stringify(message),
        success: () => {
          console.log('消息发送成功');
          resolve();
        },
        fail: (err) => {
          console.error('消息发送失败', err);
          reject(err);
        },
      });
    });
  }

  // 监听消息
  public onMessage(callback: (data: any) => void): void {
    if (!this.socketTask) {
      console.warn('WebSocket 未连接，无法监听消息');
      return;
    }

    this.socketTask.onMessage((res) => {
      callback(res.data);
    });
  }

  // 关闭连接
  public close(): void {
    if (this.socketTask) {
      this.socketTask.close({});
      this.socketTask = null;
      this.isConnected = false;
      console.log('WebSocket 已手动关闭');
    }
  }
}

export default SocketService.getInstance();
